/*
 *
 */
package com.ePadink;


import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.geom.Line2D;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.JComponent;

public class DeskSign extends JComponent
  implements IGrabber
{
  private byte m_penWidth;
  private Color m_signColor;
  private String m_signerName;
  private String m_signerDesignation;
  private String m_signerOrganisation;
  private String m_signerAddress;
  private String m_signPassword;
  private String m_version;
  private String m_deviceinfo;
  private String m_Footer;
  private String m_Tag1;
  private String m_Tag2;
  private String m_Data1;
  private String m_Data2;
  private String m_SignerUID;
  private String m_signerRemarks;
  private double m_SignDate;
  private short m_signLocale;
  private short m_signWidth;
  private short m_signHeight;
  private byte m_key1;
  private byte m_key2;
  private byte[] m_checksum;
  private byte m_CheckSumVersion;
  private boolean m_isSigned;
  private Image backGround;
  private byte Trace_Info;
  private static final int WIDTH_IS_BYTE = 1;
  private static final byte TIME_IS_INT = 2;
  private static final int X_IS_BYTE = 1;
  private static final int Y_IS_BYTE = 2;
  private static final int TIME_IS_WORD = 4;
  private static final int PRESSURE_IS_BYTE = 8;
  private static final int SEQNUM_IS_BYTE = 16;
  private int MaxX;
  private int MaxY;
  private int MinX;
  private int MinY;
  private int MinTime;
  private int MinPressure;
  private int MinSequenceNo;
  byte Trace_InfoEx;
  int index_extpoints;
  boolean extpoints_exist = false;
  int index_devextpoints;
  boolean devextpoints_exist = false;
  private byte m_penWidthX = 2;
  double dev_physicalX;
  double dev_physicalY;
  private short m_NoOfPoints;
  private short m_NoOfPointsEx;
  private Vector signPoints;
  private Vector signPointsEx;
  private byte[] rawBytes;
  private int TrcSize;
  private int STSize;
  private boolean m_tampered = false;

  private static final byte[] key = { 65, 0, 100, 0, 101, 0, 112, 0, 116, 0, 101, 0, 107, 0, 83, 0, 111, 0, 102, 0, 116, 0 };

  private MD5 md5 = null;
  private boolean lastFlag;
  private TracePoint prevPoint;
  private boolean m_EnableWhiteSpaceRemoval;
  private float m_MaxEnlargementFactor;
  private boolean m_EnableMaxEnlargementFactor;
  private boolean m_ShowLCDButtons;
  static int newvalue;
  String m_managerUID;
  byte[] uid;
  private boolean rehash = false;
  private byte[] cs = new byte[16];

  private static final int[] ks0 = { 608135816, -2052912941, 320440878, 57701188, -1542899678, 698298832, 137296536, -330404727, 1160258022, 953160567, -1101764913, 887688300, -1062458953, -914599715, 1065670069, -1253635817, -1843997223, -1988494565, -785314906, -1730169428, 805139163, -803545161, -1193168915, 1780907670, -1166241723, -248741991, 614570311, -1282315017, 134345442, -2054226922, 1667834072, 1901547113, -1537671517, -191677058, 227898511, 1921955416, 1904987480, -2112533778, 2069144605, -1034266187, -1674521287, 720527379, -976113629, 677414384, -901678824, -1193592593, -1904616272, 1614419982, 1822297739, -1340175810, -686458943, -1120842969, 2024746970, 1432378464, -430627341, -1437226092, 1464375394, 1676153920, 1439316330, 715854006, -1261675468, 289532110, -1588296017, 2087905683, -1276242927, 1668267050, 732546397, 1947742710, -832815594, -1685613794, -1344882125, 1814351708, 2050118529, 680887927, 999245976, 1800124847, -994056165, 1713906067, 1641548236, -81679983, 1216130144, 1575780402, -276538019, -377129551, -601480446, -345695352, 596196993, -745100091, 258830323, -2081144263, 772490370, -1534844924, 1774776394, -1642095778, 566650946, -152474470, 1728879713, -1412200208, 1783734482, -665571480, -1777359064, -1420741725, 1861159788, 326777828, -1170476976, 2130389656, -1578015459, 967770486, 1724537150, -2109534584, -1930525159, 1164943284, 2105845187, 998989502, -529566248, -2050940813, 1075463327, 1455516326, 1322494562, 910128902, 469688178, 1117454909, 936433444, -804646328, -619713837, 1240580251, 122909385, -2137449605, 634681816, -152510729, -469872614, -1233564613, -1754472259, 79693498, -1045868618, 1084186820, 1583128258, 426386531, 1761308591, 1047286709, 322548459, 995290223, 1845252383, -1691314900, -863943356, -1352745719, -1092366332, -567063811, 1712269319, 422464435, -1060394921, 1170764815, -771006663, -1177289765, 1434042557, 442511882, -694091578, 1076654713, 1738483198, -81812532, -1901729288, -617471240, 1014306527, -43947243, 793779912, -1392160085, 842905082, -48003232, 1395751752, 1040244610, -1638115397, -898659168, 445077038, -552113701, -717051658, 679411651, -1402522938, -1940957837, 1767581616, -1144366904, -503340195, -1192226400, 284835224, -48135240, 1258075500, 768725851, -1705778055, -1225243291, -762426948, 1274779536, -505548070, -1530167757, 1660621633, -823867672, -283063590, 913787905, -797008130, 737222580, -1780753843, -1366257256, -357724559, 1804850592, -795946544, -1345903136, -1908647121, -1904896841, -1879645445, -233690268, -2004305902, -1878134756, 1336762016, 1754252060, -774901359, -1280786003, 791618072, -1106372745, -361419266, -1962795103, -442446833, -1250986776, 413987798, -829824359, -1264037920, -49028937, 2093235073, -760370983, 375366246, -2137688315, -1815317740, 555357303, -424861595, 2008414854, -950779147, -73583153, -338841844, 2067696032, -700376109, -1373733303, 2428461, 544322398, 577241275, 1471733935, 610547355, -267798242, 1432588573, 1507829418, 2025931657, -648391809, 545086370, 48609733, -2094660746, 1653985193, 298326376, 1316178497, -1287180854, 2064951626, 458293330, -1705826027, -703637697, -1130641692, 727753846, -2115603456 };

  private static final int[] ks1 = { -224990101, 705550613, -1235000031, -407242314, -13368018, -981117340, 1404054877, -1449160799, 146425753, 1854211946, 1266315497, -1246549692, -613086930, -1004984797, -1385257296, 1235738493, -1662099272, -1880247706, -324367247, 1771706367, 1449415276, -1028546847, 422970021, 1963543593, -1604775104, -468174274, 1062508698, 1531092325, 1804592342, -1711849514, -1580033017, -269995787, 1294809318, -265986623, 1289560198, -2072974554, 1669523910, 35572830, 157838143, 1052438473, 1016535060, 1802137761, 1753167236, 1386275462, -1214491899, -1437595849, 1040679964, 2145300060, -1904392980, 1461121720, -1338320329, -263189491, -266592508, 33600511, -1374882534, 1018524850, 629373528, -603381315, -779021319, 2091462646, -1808644237, 586499841, 988145025, 935516892, -927631820, -1695294041, -1455136442, 265290510, -322386114, -1535828415, -499593831, 1005194799, 847297441, 406762289, 1314163512, 1332590856, 1866599683, -167115585, 750260880, 613907577, 1450815602, -1129346641, -560302305, -644675568, -1282691566, -590397650, 1427272223, 778793252, 1343938022, -1618686585, 2052605720, 1946737175, -1130390852, -380928628, -327488454, -612033030, 1661551462, -1000029230, -283371449, 840292616, -582796489, 616741398, 312560963, 711312465, 1351876610, 322626781, 1910503582, 271666773, -2119403562, 1594956187, 70604529, -677132437, 1007753275, 1495573769, -225450259, -1745748998, -1631928532, 504708206, -2031925904, -353800271, -2045878774, 1514023603, 1998579484, 1312622330, 694541497, -1712906993, -2143385130, 1382467621, 776784248, -1676627094, -971698502, -1797068168, -1510196141, 503983604, -218673497, 907881277, 423175695, 432175456, 1378068232, -149744970, -340918674, -356311194, -474200683, -1501837181, -1317062703, 26017576, -1020076561, -1100195163, 1700274565, 1756076034, -288447217, -617638597, 720338349, 1533947780, 354530856, 688349552, -321042571, 1637815568, 332179504, -345916010, 53804574, -1442618417, -1250730864, 1282449977, -711025141, -877994476, -288586052, 1617046695, -1666491221, -1292663698, 1686838959, 431878346, -1608291911, 1700445008, 1080580658, 1009431731, 832498133, -1071531785, -1688990951, -2023776103, -1778935426, 1648197032, -130578278, -1746719369, 300782431, 375919233, 238389289, -941219882, -1763778655, 2019080857, 1475708069, 455242339, -1685863425, 448939670, -843904277, 1395535956, -1881585436, 1841049896, 1491858159, 885456874, -30872223, -293847949, 1565136089, -396052509, 1108368660, 540939232, 1173283510, -1549095958, -613658859, -87339056, -951913406, -278217803, 1699691293, 1103962373, -669091426, -2038084153, -464828566, 1031889488, -815619598, 1535977030, -58162272, -1043876189, 2132092099, 1774941330, 1199868427, 1452454533, 157007616, -1390851939, 342012276, 595725824, 1480756522, 206960106, 497939518, 591360097, 863170706, -1919713727, -698356495, 1814182875, 2094937945, -873565088, 1082520231, -831049106, -1509457788, 435703966, -386934699, 1641649973, -1452693590, -989067582, 1510255612, -2146710820, -1639679442, -1018874748, -36346107, 236887753, -613164077, 274041037 };

  private static final int[] ks2 = { -976997275, 1899903192, 1026095262, -244449504, 356393447, -1884275382, -421290197, -612127241, -381855128, -1803468553, -162781668, -1805047500, 1091903735, 1979897079, -1124832466, -727580568, -737663887, 857797738, 1136121015, 1342202287, 507115054, -1759230650, 337727348, -1081374656, 1301675037, -1766485585, 1895095763, 1721773893, -1078195732, 62756741, 2142006736, 835421444, -1762973773, 1442658625, -635090970, -1412822374, 676362277, 1392781812, 170690266, -373920261, 1759253602, -683120384, 1745797284, 664899054, 1329594018, -393761396, -1249058810, 2062866102, -1429332356, -751345684, -830954599, 1080764994, 553557557, -638351943, -298199125, 991055499, 499776247, 1265440854, 648242737, -354183246, 980351604, -581221582, 1749149687, -898096901, -83167922, -654396521, 1161844396, -1169648345, 1431517754, 545492359, -26498633, -795437749, 1437099964, -1592419752, -861329053, -1713251533, -1507177898, 1060185593, 1593081372, -1876348548, -34019326, 69676912, -2135222948, 86519011, -1782508216, -456757982, 1220612927, -955283748, 133810670, 1090789135, 1078426020, 1569222167, 845107691, -711212847, -222510705, 1091646820, 628848692, 1613405280, -537335645, 526609435, 236106946, 48312990, -1352249391, -892239595, 1797494240, 859738849, 992217954, -289490654, -2051890674, -424014439, -562951028, 765654824, -804095931, -1783130883, 1685915746, -405998096, 1414112111, -2021832454, -1013056217, -214004450, 172450625, -1724973196, 980381355, -185008841, -1475158944, -1578377736, -1726226100, -613520627, -964995824, 1835478071, 660984891, -590288892, -248967737, -872349789, -1254551662, 1762651403, 1719377915, -824476260, -1601057013, -652910941, -1156370552, 1364962596, 2073328063, 1983633131, 926494387, -871278215, -2144935273, -198299347, 1749200295, -966120645, 309677260, 2016342300, 1779581495, -1215147545, 111262694, 1274766160, 443224088, 298511866, 1025883608, -488520759, 1145181785, 168956806, -653464466, -710153686, 1689216846, -628709281, -1094719096, 1692713982, -1648590761, -252198778, 1618508792, 1610833997, -771914938, -164094032, 2001055236, -684262196, -2092799181, -266425487, -1333771897, 1006657119, 2006996926, -1108824540, 1430667929, -1084739999, 1314452623, -220332638, -193663176, -2021016126, 1399257539, -927756684, -1267338667, 1190975929, 2062231137, -1960976508, -2073424263, -1856006686, 1181637006, 548689776, -1932175983, -922558900, -1190417183, -1149106736, 296247880, 1970579870, -1216407114, -525738999, 1714227617, -1003338189, -396747006, 166772364, 1251581989, 493813264, 448347421, 195405023, -1584991729, 677966185, -591930749, 1463355134, -1578971493, 1338867538, 1343315457, -1492745222, -1610435132, 233230375, -1694987225, 2000651841, -1017099258, 1638401717, -266896856, -1057650976, 6314154, 819756386, 300326615, 590932579, 1405279636, -1027467724, -1144263082, -1866680610, -335774303, -833020554, 1862657033, 1266418056, 963775037, 2089974820, -2031914401, 1917689273, 448879540, -744572676, -313240200, 150775221, -667058989, 1303187396, 1734335097, -479771840, 146436021, 1461446943 };

  private static final int[] ks3 = { 508620638, -1318983944, -1568336679, 1817252668, 1876281319, 1457606340, 908771278, -574175177, -677760460, -1838972398, 1729034894, 1080033504, 976866871, -738527793, -1413318857, 1522871579, 1555064734, 1336096578, -746444992, -1715692610, -720269667, -1089506539, -701686658, -956251013, -1215554709, 564236357, -1301368386, 1781952180, 1464380207, -1131123079, -962365742, 1699332808, 1393555694, 1183702653, -713881059, 1288719814, 691649499, -1447410096, -1399511320, -1101077756, -1577396752, 1781354906, 1676643554, -1702433246, -1064713544, 1126444790, -1524759638, -1661808476, -2084544070, -1679201715, -1880812208, -1167828010, 673620729, -1489356063, 1269405062, -279616791, -953159725, -145557542, 1057255273, 2012875353, -2132498155, -2018474495, -1693849939, 993977747, -376373926, -1640704105, 753973209, 36408145, -1764381638, 25011837, -774947114, 2088578344, 530523599, -1376601957, 1524020338, 1518925132, -534139791, -535190042, 1202760957, -309069157, -388774771, 674977740, -120232407, 2031300136, 2019492241, -311074731, -141160892, -472686964, 352677332, -1997247046, 60907813, 90501309, -1007968747, 1016092578, -1759044884, -1455814870, 457141659, 509813237, -174299397, 652014361, 1966332200, -1319764491, 55981186, -1967506245, 676427537, -1039476232, -1412673177, -861040033, 1307055953, 942726286, 933058658, -1826555503, -361066302, -79791154, 1361170020, 2001714738, -1464409218, -1020707514, 1222529897, 1679025792, -1565652976, -580013532, 1770335741, 151462246, -1281735158, 1682292957, 1483529935, 471910574, 1539241949, 458788160, -858652289, 1807016891, -576558466, 978976581, 1043663428, -1129001515, 1927990952, -94075717, -1922690386, -1086558393, -761535389, 1412390302, -1362987237, -162634896, 1947078029, -413461673, -126740879, -1353482915, 1077988104, 1320477388, 886195818, 18198404, -508558296, -1785185763, 112762804, -831610808, 1866414978, 891333506, 18488651, 661792760, 1628790961, -409780260, -1153795797, 876946877, -1601685023, 1372485963, 791857591, -1608533303, -534984578, -1127755274, -822013501, -1578587449, 445679433, -732971622, -790962485, -720709064, 54117162, -963561881, -1913048708, -525259953, -140617289, 1140177722, -220915201, 668550556, -1080614356, 367459370, 261225585, -1684794075, -85617823, -826893077, -1029151655, 314222801, -1228863650, -486184436, 282218597, -888953790, -521376242, 379116347, 1285071038, 846784868, -1625320142, -523005217, -744475605, -1989021154, 453669953, 1268987020, -977374944, -1015663912, -550133875, -1684459730, -435458233, 266596637, -447948204, 517658769, -832407089, -851542417, 370717030, -47440635, -2070949179, -151313767, -182193321, -1506642397, -1817692879, 1456262402, -1393524382, 1517677493, 1846949527, -1999473716, -560569710, -2118563376, 1280348187, 1908823572, -423180355, 846861322, 1172426758, -1007518822, -911584259, 1655181056, -1155153950, 901632758, 1897031941, -1308360158, -1228157060, -847864789, 1393639104, 373351379, 950779232, 625454576, -1170726756, -146354570, 2007998917, 544563296, -2050228658, -1964470824, 2058025392, 1291430526 };
  private static final int MAXKEYBYTES = 56;
  private static final int N = 16;
  private static final int noErr = 0;
  private static final int DATAERROR = -1;
  private static final int KEYBYTES = 8;
  private int[][] S = new int[4][256];
  private int xleft;
  private int xright;
  private int[] P = { 608135816, -2052912941, 320440878, 57701188, -1542899678, 698298832, 137296536, -330404727, 1160258022, 953160567, -1101764913, 887688300, -1062458953, -914599715, 1065670069, -1253635817, -1843997223, -1988494565 };

  private native byte[] showPad(String paramString1, String paramString2, String paramString3, String paramString4, String paramString5, String paramString6, boolean paramBoolean1, boolean paramBoolean2);

  private native int openConnectionNative();

  private native int closeConnectionNative();

  private native int showMessageNative(String paramString, int paramInt);

  public DeskSign()
  {
    setSize(200, 200);
    setBackground(Color.white);
    this.m_penWidth = 1;
    this.m_signColor = Color.black;
    this.m_signerRemarks = "";
    this.m_signLocale = 0;
    this.m_Data1 = "";
    this.m_isSigned = false;
    this.m_checksum = new byte[16];
    this.m_SignerUID = "000000000000000000000000000000000000";

    this.m_EnableWhiteSpaceRemoval = true;
    this.m_MaxEnlargementFactor = 1.25F;
    this.m_EnableMaxEnlargementFactor = true;
    this.m_ShowLCDButtons = true;
  }

  public void update(Graphics g)
  {
    paint(g);
  }

  public boolean isSigned() {
    return this.m_isSigned;
  }

  public void paint(Graphics context)
  {
    if (isOpaque()) {
      context.setColor(Color.lightGray);
      context.draw3DRect(0, 0, getSize().width - 1, getSize().height - 1, true);
      context.draw3DRect(2, 2, getSize().width - 5, getSize().height - 5, false);
      context.setColor(Color.white);
      context.fillRect(2, 2, getSize().width - 5, getSize().height - 5);
    }

    if (this.m_isSigned) {
      if (this.extpoints_exist) {
        if (this.devextpoints_exist)
          drawSignEx1(context);
        else
          drawSignEx(context);
      }
      else {
        drawSign(context);
      }
    }
    if (this.m_tampered) {
      context.setColor(Color.red);
      context.drawLine(0, 0, getSize().width, getSize().height);
      context.drawLine(1, 0, getSize().width, getSize().height - 1);
      context.drawLine(getSize().width, 0, 0, getSize().height);
      context.drawLine(getSize().width - 1, 0, 0, getSize().height - 1);
    }
  }

  public void clear()
  {
    if (!this.m_isSigned) {
      return;
    }
    this.m_penWidth = 0;
    this.m_signColor = null;
    this.m_signerName = null;
    this.m_SignerUID = null;
    this.m_signerRemarks = null;
    this.m_SignDate = 0.0D;
    this.m_signLocale = 0;

    this.m_signWidth = 0;
    this.m_signHeight = 0;
    this.m_key1 = 0;
    this.m_key2 = 0;

    this.m_Data1 = null;

    this.m_checksum = null;
    this.m_CheckSumVersion = 0;

    this.m_isSigned = false;

    if (this.extpoints_exist)
      this.Trace_InfoEx = 0;
    else {
      this.Trace_Info = 0;
    }

    this.m_NoOfPoints = 0;
    this.m_NoOfPointsEx = 0;

    this.rawBytes = null;
    this.TrcSize = 0;
    this.STSize = 0;

    this.md5 = null;

    this.lastFlag = false;
    this.prevPoint = null;
    this.m_tampered = false;

    this.m_isSigned = false;
    if (this.extpoints_exist)
      this.signPointsEx.removeAllElements();
    else {
      this.signPoints.removeAllElements();
    }
    this.signPoints = null;
    this.signPointsEx = null;
    this.MaxX = 0;
    this.MaxY = 0;
    this.MinX = 0;
    this.MinY = 0;
    this.MinTime = 0;
    this.MinPressure = 0;
    this.MinSequenceNo = 0;
    this.Trace_InfoEx = 0;
    this.index_extpoints = -1;
    this.devextpoints_exist = false;
    this.index_devextpoints = -1;
    this.extpoints_exist = false;
    this.rehash = false;
    repaint();
  }

  public boolean canSign() {
    return (this.m_signerName != null) && (this.m_signerName.length() != 0);
  }

  private boolean validateSignerUID(String suid) {
    if (suid.length() != 36) {
      return false;
    }

    byte[] sUID = convertToByte(suid);
    if (sUID.length == 18) {
      return true;
    }

    return false;
  }

  public int openConnection()
  {
    try
    {
      System.loadLibrary("ePadInkNative");
      return openConnectionNative();
    }
    catch (Exception ex)
    {
      System.out.println("Could not Load the ePadInkNative.dll library");
      ex.printStackTrace();
    }return -2;
  }

  public int closeConnection()
  {
    try
    {
      System.loadLibrary("ePadInkNative");
      return closeConnectionNative();
    }
    catch (Exception ex)
    {
      System.out.println("Could not Load the ePadInkNative.dll library");
      ex.printStackTrace();
    }return -2;
  }

  public int showMessage(String message, int BUTTON_STYLE)
  {
    try
    {
      System.loadLibrary("ePadInkNative");
      if ((message != null) && (message.length() > 0)) {
        return showMessageNative(message, BUTTON_STYLE);
      }

      return 0;
    }
    catch (Exception ex) {
      System.out.println("Could not Load the ePadInkNative.dll library");
      ex.printStackTrace();
    }return 0;
  }

  public void onHandleData(int xpos, int ypos, int screenid, int eventid)
  {
    System.out.println("The callback event fired");
  }

  public void signNow(String name, String desg, String org, String Addr, String Footer, String reserved, boolean breserved1, boolean showOptions, boolean breserved2, IDocInfo idi)
    throws ValidationException
  {
    this.m_signerName = name;
    this.m_signerDesignation = desg;
    this.m_signerOrganisation = org;
    this.m_signerAddress = Addr;
    this.m_Footer = Footer;
    this.m_signerRemarks = "";
    boolean cansign = false;
    this.m_checksum = new byte[16];
    try {
      cansign = canSign();
    } catch (Exception expn1) {
      expn1.printStackTrace();
    }
    try
    {
      System.loadLibrary("eSJDeskPad");
    } catch (Exception ex) {
      System.out.println("Could not Load the eSJDeskPad.dll library");
      ex.printStackTrace();
    }

    try
    {
      this.md5 = new MD5();
    } catch (Exception e) {
      System.out.println("Can not create MD5 Object");
    }

    if (cansign) {
      idi.feedGrabber(this);
      this.m_CheckSumVersion = idi.getVersion();

      this.rawBytes = showPad("", name, desg, org, Addr, Footer, showOptions, this.m_ShowLCDButtons);

      if (this.rawBytes.length > 0)
      {
        System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
        newvalue = this.rawBytes.length;
        byte[] tempBytes = new byte[87];
        System.arraycopy(this.rawBytes, 0, tempBytes, 0, 87);
        readHeader(tempBytes);
        tempBytes = new byte[this.rawBytes.length - 87];
        System.arraycopy(this.rawBytes, 87, tempBytes, 0, this.rawBytes.length - 87);

        readContent(tempBytes);
        this.m_isSigned = true;
        repaint();
      } else {
        this.m_isSigned = false;
        this.rawBytes = null;
      }
    } else {
      throw new ValidationException("Signer name must be set");
    }
  }

  public void signNowEx(String name, String desg, String org, String Addr, String Footer, boolean showOptions, IDocInfo idi)
    throws ValidationException
  {
    this.m_signerName = name;
    this.m_signerDesignation = desg;
    this.m_signerOrganisation = org;
    this.m_signerAddress = Addr;
    this.m_Footer = Footer;
    this.m_signerRemarks = "";
    boolean cansign = false;
    this.m_checksum = new byte[16];
    try {
      cansign = canSign();
    } catch (Exception expn1) {
      expn1.printStackTrace();
    }
    try
    {
      System.loadLibrary("eSJDeskPad");
    } catch (Exception ex) {
      System.out.println("Could not Load the eSJDeskPad.dll library");
      ex.printStackTrace();
    }

    try
    {
      this.md5 = new MD5();
    } catch (Exception e) {
      System.out.println("Can not create MD5 Object");
    }

    if (cansign) {
      idi.feedGrabber(this);
      this.m_CheckSumVersion = idi.getVersion();

      this.rawBytes = showPad("", name, desg, org, Addr, Footer, showOptions, this.m_ShowLCDButtons);

      if (this.rawBytes.length > 0)
      {
        System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
        newvalue = this.rawBytes.length;
        byte[] tempBytes = new byte[87];
        System.arraycopy(this.rawBytes, 0, tempBytes, 0, 87);
        readHeader(tempBytes);
        tempBytes = new byte[this.rawBytes.length - 87];
        System.arraycopy(this.rawBytes, 87, tempBytes, 0, this.rawBytes.length - 87);

        readContent(tempBytes);
        this.m_isSigned = true;
        repaint();
      } else {
        this.m_isSigned = false;
        this.rawBytes = null;
      }
    } else {
      throw new ValidationException("Signer name must be set");
    }
  }

  public void signNow(String ID, String name, boolean breserved1, boolean showOptions, boolean breserved2, IDocInfo idi)
    throws ValidationException
  {
    this.m_signerName = name;
    this.m_signerDesignation = "none";
    this.m_signerOrganisation = "none";
    this.m_signerAddress = "none";
    this.m_Footer = "none";
    this.m_signerRemarks = "";
    this.m_checksum = new byte[16];
    boolean cansign = false;
    try {
      cansign = canSign();
    } catch (Exception expn1) {
      expn1.printStackTrace();
    }
    try
    {
      System.loadLibrary("eSJDeskPad");
    } catch (Exception ex) {
      System.out.println("Could not Load the eSJDeskPad.dll library");
      ex.printStackTrace();
    }

    try
    {
      this.md5 = new MD5();
    } catch (Exception e) {
      System.out.println("Can not create MD5 Object");
    }

    if (cansign) {
      idi.feedGrabber(this);
      this.m_CheckSumVersion = idi.getVersion();

      this.rawBytes = showPad(ID, name, "none", "none", "none", "none", showOptions, this.m_ShowLCDButtons);

      if (this.rawBytes.length > 0) {
        System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
        newvalue = this.rawBytes.length;
        byte[] tempBytes = new byte[87];
        System.arraycopy(this.rawBytes, 0, tempBytes, 0, 87);
        readHeader(tempBytes);
        tempBytes = new byte[this.rawBytes.length - 87];
        System.arraycopy(this.rawBytes, 87, tempBytes, 0, this.rawBytes.length - 87);

        readContent(tempBytes);
        this.m_isSigned = true;
        repaint();
      } else {
        this.m_isSigned = false;
        this.rawBytes = null;
      }
    } else {
      throw new ValidationException("Signer name must be set");
    }
  }

  public void signNowEx(String ID, String name, boolean showOptions, IDocInfo idi)
    throws ValidationException
  {
    this.m_signerName = name;
    this.m_signerDesignation = "none";
    this.m_signerOrganisation = "none";
    this.m_signerAddress = "none";
    this.m_Footer = "none";
    this.m_signerRemarks = "";
    this.m_checksum = new byte[16];
    boolean cansign = false;
    try {
      cansign = canSign();
    } catch (Exception expn1) {
      expn1.printStackTrace();
    }
    try
    {
      System.loadLibrary("eSJDeskPad");
    } catch (Exception ex) {
      System.out.println("Could not Load the eSJDeskPad.dll library");
      ex.printStackTrace();
    }

    try
    {
      this.md5 = new MD5();
    } catch (Exception e) {
      System.out.println("Can not create MD5 Object");
    }

    if (cansign) {
      idi.feedGrabber(this);
      this.m_CheckSumVersion = idi.getVersion();

      this.rawBytes = showPad(ID, name, "none", "none", "none", "none", showOptions, this.m_ShowLCDButtons);

      if (this.rawBytes.length > 0) {
        System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
        newvalue = this.rawBytes.length;
        byte[] tempBytes = new byte[87];
        System.arraycopy(this.rawBytes, 0, tempBytes, 0, 87);
        readHeader(tempBytes);
        tempBytes = new byte[this.rawBytes.length - 87];
        System.arraycopy(this.rawBytes, 87, tempBytes, 0, this.rawBytes.length - 87);

        readContent(tempBytes);
        this.m_isSigned = true;
        repaint();
      } else {
        this.m_isSigned = false;
        this.rawBytes = null;
      }
    } else {
      throw new ValidationException("Signer name must be set");
    }
  }

  public void signNowEx(IDocInfo idi)
    throws ValidationException
  {
    this.m_Data1 = "";
    this.m_signerName = "none";
    this.m_signerDesignation = "none";
    this.m_signerOrganisation = "none";
    this.m_signerAddress = "none";
    this.m_Footer = "none";
    this.m_signerRemarks = "";
    this.m_checksum = new byte[16];

    boolean cansign = false;
    try {
      cansign = canSign();
    } catch (Exception expn1) {
      expn1.printStackTrace();
    }
    try {
      System.loadLibrary("eSJDeskPad");
    } catch (Exception ex) {
      System.out.println("Could not Load the eSJDeskPad.dll library");
      ex.printStackTrace();
    }

    try
    {
      this.md5 = new MD5();
    } catch (Exception e) {
      System.out.println("Can not create MD5 Object");
    }

    if (cansign)
    {
      idi.feedGrabber(this);
      this.m_CheckSumVersion = idi.getVersion();

      this.rawBytes = showPad("none", "none", "none", "none", "none", "none", true, this.m_ShowLCDButtons);

      if (this.rawBytes.length > 0)
      {
        System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
        newvalue = this.rawBytes.length;
        byte[] tempBytes = new byte[87];
        System.arraycopy(this.rawBytes, 0, tempBytes, 0, 87);
        readHeader(tempBytes);
        tempBytes = new byte[this.rawBytes.length - 87];
        System.arraycopy(this.rawBytes, 87, tempBytes, 0, this.rawBytes.length - 87);

        readContent(tempBytes);
        this.m_isSigned = true;
        repaint();
      } else {
        this.m_isSigned = false;
        this.rawBytes = null;
      }
    } else {
      throw new ValidationException("Signer name must be set");
    }
  }

  public void signNow(String ID, String name, String desg, String org, String Addr, String Footer, String reerved, boolean breserved1, boolean showOptions, boolean breserved2, IDocInfo idi)
    throws ValidationException
  {
    this.m_Data1 = ID;
    this.m_signerName = name;
    this.m_signerDesignation = desg;
    this.m_signerOrganisation = org;
    this.m_signerAddress = Addr;
    this.m_Footer = Footer;
    this.m_signerRemarks = "";
    this.m_checksum = new byte[16];
    this.m_signerRemarks = "";
    boolean cansign = false;
    int ip = 0;
    try {
      cansign = canSign();
    } catch (Exception expn1) {
      expn1.printStackTrace();
    }
    try
    {
      System.loadLibrary("eSJDeskPad");
    } catch (Exception ex) {
      System.out.println("Could not Load the eSJDeskPad.dll library");
      ex.printStackTrace();
    }

    try
    {
      this.md5 = new MD5();
    } catch (Exception e) {
      System.out.println("Can not create MD5 Object");
    }

    if (cansign) {
      idi.feedGrabber(this);
      this.m_CheckSumVersion = idi.getVersion();

      this.rawBytes = showPad(ID, name, desg, org, Addr, Footer, showOptions, this.m_ShowLCDButtons);

      if (this.rawBytes.length > 0) {
        System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
        newvalue = this.rawBytes.length;
        byte[] tempBytes = new byte[87];
        System.arraycopy(this.rawBytes, 0, tempBytes, 0, 87);
        readHeader(tempBytes);
        tempBytes = new byte[this.rawBytes.length - 87];
        System.arraycopy(this.rawBytes, 87, tempBytes, 0, this.rawBytes.length - 87);

        readContent(tempBytes);
        this.m_isSigned = true;
        repaint();
      } else {
        this.m_isSigned = false;
        this.rawBytes = null;
      }
    } else {
      throw new ValidationException("Signer name must be set");
    }
  }

  public void signNowEx(String ID, String name, String desg, String org, String Addr, String Footer, boolean showOptions, IDocInfo idi)
    throws ValidationException
  {
    this.m_Data1 = ID;
    this.m_signerName = name;
    this.m_signerDesignation = desg;
    this.m_signerOrganisation = org;
    this.m_signerAddress = Addr;
    this.m_Footer = Footer;
    this.m_signerRemarks = "";
    this.m_checksum = new byte[16];
    this.m_signerRemarks = "";
    boolean cansign = false;
    int ip = 0;
    try {
      cansign = canSign();
    } catch (Exception expn1) {
      expn1.printStackTrace();
    }
    try
    {
      System.loadLibrary("eSJDeskPad");
    } catch (Exception ex) {
      System.out.println("Could not Load the eSJDeskPad.dll library");
      ex.printStackTrace();
    }

    try
    {
      this.md5 = new MD5();
    } catch (Exception e) {
      System.out.println("Can not create MD5 Object");
    }

    if (cansign) {
      idi.feedGrabber(this);
      this.m_CheckSumVersion = idi.getVersion();

      this.rawBytes = showPad(ID, name, desg, org, Addr, Footer, showOptions, this.m_ShowLCDButtons);

      if (this.rawBytes.length > 0) {
        System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
        newvalue = this.rawBytes.length;
        byte[] tempBytes = new byte[87];
        System.arraycopy(this.rawBytes, 0, tempBytes, 0, 87);
        readHeader(tempBytes);
        tempBytes = new byte[this.rawBytes.length - 87];
        System.arraycopy(this.rawBytes, 87, tempBytes, 0, this.rawBytes.length - 87);

        readContent(tempBytes);
        this.m_isSigned = true;
        repaint();
      } else {
        this.m_isSigned = false;
        this.rawBytes = null;
      }
    } else {
      throw new ValidationException("Signer name must be set");
    }
  }

  public void openSign1(String str)
  {
    if ((str != null) && (str.length() > 0)) {
      this.m_checksum = new byte[16];
      this.md5 = new MD5();
      byte[] myArr = new Base64Format().decode64(str);
      openSign(myArr);
    }
  }

  public void openSign(byte[] bytearr)
  {
    ByteArrayOutputStream bosdec = new ByteArrayOutputStream();
    ByteArrayInputStream besdec = new ByteArrayInputStream(bytearr);
    byte[] key = { 65, 0, 100, 0, 101, 0, 112, 0, 116, 0, 101, 0, 107, 0, 83, 0, 111, 0, 102, 0, 116, 0 };

    decrypt(bosdec, besdec, key);
    bytearr = bosdec.toByteArray();
    besdec.reset();
    try
    {
      ByteArrayInputStream bis = new ByteArrayInputStream(bytearr);
      newvalue = bis.available();
      byte[] myarr = new byte[bis.available()];
      bis.read(myarr);

      this.rawBytes = new byte[myarr.length];
      System.arraycopy(myarr, 0, this.rawBytes, 0, myarr.length);
      ByteArrayInputStream bis4 = new ByteArrayInputStream(myarr);
      byte[] readarr = new byte[87];
      for (int i = 0; i <= 86; i++) {
        readarr[i] = ((byte)bis4.read());
      }
      readHeader(readarr);
      byte[] readarr1 = new byte[newvalue - 87];
      for (int i = 0; i <= newvalue - 87 - 1; i++) {
        readarr1[i] = ((byte)bis4.read());
      }
      readContent(readarr1);

      this.m_isSigned = true;
      repaint();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public String getGifString(String signstr, int w, int h)
  {
    byte[] tempBytes = new Base64Format().decode64(signstr);
    ByteArrayOutputStream bosdec = new ByteArrayOutputStream();
    ByteArrayInputStream besdec = new ByteArrayInputStream(tempBytes);
    byte[] key = { 65, 0, 100, 0, 101, 0, 112, 0, 116, 0, 101, 0, 107, 0, 83, 0, 111, 0, 102, 0, 116, 0 };

    decrypt(bosdec, besdec, key);
    tempBytes = bosdec.toByteArray();
    besdec.reset();

    String gifstr = "";
    SaveImage si = new SaveImage();
    si.setSignImageThickness(this.m_penWidthX);
    si.enableWhiteSpaceRemoval(this.m_EnableWhiteSpaceRemoval);
    si.enableMaxEnlargementFactor(this.m_EnableMaxEnlargementFactor);
    si.setMaxEnlargementFactor(this.m_MaxEnlargementFactor);
    byte[] gifbytes = si.getGifImageBytes(tempBytes, w, h);
    if (gifbytes.length > 0) {
      gifstr = new Base64Format().encode64(gifbytes);
    }
    return gifstr;
  }

  public String getBMPString(String signstr, int w, int h)
  {
    byte[] tempBytes = new Base64Format().decode64(signstr);
    ByteArrayOutputStream bosdec = new ByteArrayOutputStream();
    ByteArrayInputStream besdec = new ByteArrayInputStream(tempBytes);
    byte[] key = { 65, 0, 100, 0, 101, 0, 112, 0, 116, 0, 101, 0, 107, 0, 83, 0, 111, 0, 102, 0, 116, 0 };

    decrypt(bosdec, besdec, key);
    tempBytes = bosdec.toByteArray();
    besdec.reset();
    String bmpstr = "";
    SaveImage si = new SaveImage();
    si.setSignImageThickness(this.m_penWidthX);
    si.enableWhiteSpaceRemoval(this.m_EnableWhiteSpaceRemoval);
    si.enableMaxEnlargementFactor(this.m_EnableMaxEnlargementFactor);
    si.setMaxEnlargementFactor(this.m_MaxEnlargementFactor);
    byte[] bmpbytes = null;
    bmpbytes = si.getBMPImageBytes(tempBytes, w, h);

    if (bmpbytes.length > 0) {
      bmpstr = new Base64Format().encode64(bmpbytes);
    }
    return bmpstr;
  }

  public String getJpegString(String signstr, int w, int h, int quality)
  {
    byte[] tempBytes = new Base64Format().decode64(signstr);
    ByteArrayOutputStream bosdec = new ByteArrayOutputStream();
    ByteArrayInputStream besdec = new ByteArrayInputStream(tempBytes);
    byte[] key = { 65, 0, 100, 0, 101, 0, 112, 0, 116, 0, 101, 0, 107, 0, 83, 0, 111, 0, 102, 0, 116, 0 };

    decrypt(bosdec, besdec, key);
    tempBytes = bosdec.toByteArray();
    besdec.reset();

    String jpegstr = "";
    SaveImage si = new SaveImage();
    si.setSignImageThickness(this.m_penWidthX);
    si.enableWhiteSpaceRemoval(this.m_EnableWhiteSpaceRemoval);
    si.enableMaxEnlargementFactor(this.m_EnableMaxEnlargementFactor);
    si.setMaxEnlargementFactor(this.m_MaxEnlargementFactor);
    byte[] jpegbytes = si.getJpegImageBytes(tempBytes, w, h, quality);
    if (jpegbytes.length > 0) {
      jpegstr = new Base64Format().encode64(jpegbytes);
    }

    return jpegstr;
  }

  public String getPNGString(String signstr, int w, int h, boolean transparency)
  {
    byte[] tempBytes = new Base64Format().decode64(signstr);
    ByteArrayOutputStream bosdec = new ByteArrayOutputStream();
    ByteArrayInputStream besdec = new ByteArrayInputStream(tempBytes);
    byte[] key = { 65, 0, 100, 0, 101, 0, 112, 0, 116, 0, 101, 0, 107, 0, 83, 0, 111, 0, 102, 0, 116, 0 };

    decrypt(bosdec, besdec, key);
    tempBytes = bosdec.toByteArray();
    besdec.reset();
    String gifstr = "";
    SaveImage si = new SaveImage();
    si.setSignImageThickness(this.m_penWidthX);
    si.enableWhiteSpaceRemoval(this.m_EnableWhiteSpaceRemoval);
    si.enableMaxEnlargementFactor(this.m_EnableMaxEnlargementFactor);
    si.setMaxEnlargementFactor(this.m_MaxEnlargementFactor);
    byte[] gifbytes = si.getPngImageBytes(tempBytes, w, h, transparency);
    if (gifbytes.length > 0) {
      gifstr = new Base64Format().encode64(gifbytes);
    }
    return gifstr;
  }

  public void setSignThickness(byte signthickness)
  {
    if ((signthickness <= 0) || (signthickness > 9))
      this.m_penWidthX = 2;
    else {
      this.m_penWidthX = signthickness;
    }
    repaint();
    repaint();
  }

  public void enableWhiteSpaceRemoval(boolean state) {
    this.m_EnableWhiteSpaceRemoval = state;
  }

  public void setMaxEnlargementFactor(float value)
  {
    if ((value < 1.0F) || (value > 2.0F))
      this.m_MaxEnlargementFactor = 1.25F;
    else
      this.m_MaxEnlargementFactor = value;
  }

  public void setEnableLCDButtons(boolean show)
  {
    this.m_ShowLCDButtons = show;
  }

  public void enableMaxEnlargementFactor(boolean value) {
    this.m_EnableMaxEnlargementFactor = value;
  }

  public void setClaimerID(String cid)
  {
    if (!isSigned())
      this.m_Data1 = cid;
  }

  public String getClaimerID()
  {
    if (isSigned()) {
      return this.m_Data1;
    }
    return null;
  }

  public void setSignerUID(String suid) throws ValidationException {
    if (!isSigned())
    {
      if (validateSignerUID(suid))
        this.m_SignerUID = suid;
      else
        throw new ValidationException("Invalid SignerUID,cano't set");
    }
  }

  public String getSignerUID()
  {
    if (isSigned()) {
      return this.m_SignerUID;
    }
    return null;
  }

  public String getSignerName() {
    return this.m_signerName;
  }

  public String getSignerDesignation() {
    return this.m_signerDesignation;
  }

  public String getSignerOrganisation() {
    return this.m_signerOrganisation;
  }

  public String getSignerAddress() {
    return this.m_signerAddress;
  }

  public String getInutDeviceInfo()
  {
    return this.m_deviceinfo;
  }

  public Date getsignDate() {
    long l = System.currentTimeMillis();

    return new Date(l);
  }

  public boolean hasSigner()
  {
    return (this.m_signerName != null) && (this.m_signerName.length() != 0);
  }

  private byte[] convertToByte(String str) {
    byte[] thisArray = new byte[str.length() / 2];
    int lbit = 0; int hbit = 0;
    int i = 0; for (int Index = 0; i <= str.length() - 1; Index++) {
      lbit = Character.digit(str.charAt(i), 16);
      i++;
      if (i == str.length()) {
        break;
      }
      hbit = Character.digit(str.charAt(i), 16);
      thisArray[Index] = ((byte)(lbit * 16 + hbit));

      i++;
    }

    return thisArray;
  }

  private void readHeader(byte[] HeaderBytes)
  {
    this.m_penWidth = HeaderBytes[0];
    int colorInt = HeaderBytes[3] & 0xFF | (HeaderBytes[2] & 0xFF) << 8 | (HeaderBytes[1] & 0xFF) << 16;

    this.m_signColor = new Color(colorInt);
    this.m_signLocale = ((short)(HeaderBytes[5] & 0xFF));
    int tempInt = HeaderBytes[6] & 0xFF;
    if (tempInt > 128)
      tempInt = -(this.m_signLocale + (tempInt - 128 << 8));
    else {
      tempInt = this.m_signLocale + (tempInt << 8);
    }
    this.m_signLocale = ((short)tempInt);
    this.m_signWidth = ((short)(HeaderBytes[7] & 0xFF | (HeaderBytes[8] & 0xFF) << 8));

    this.m_signHeight = ((short)(HeaderBytes[9] & 0xFF));
    StringBuffer tempStr = new StringBuffer(36);
    for (int i = 0; i < 18; i++) {
      char c = Character.forDigit(HeaderBytes[(10 + i)] & 0xF, 16);
      tempStr.append(c);
      c = Character.forDigit(HeaderBytes[(10 + i)] & 0xF0, 16);
      tempStr.append(c);
    }
    this.m_SignerUID = tempStr.toString();
    long tempLong = 0L;
    for (int z = 0; z < 16; z++) {
      this.m_checksum[z] = HeaderBytes[(z + 49)];
    }
    for (int i = 65; i < 73; i++) {
      tempLong |= (HeaderBytes[i] & 0xFF) << (i - 65) * 8;
    }
    
    Long l = new Long(tempLong);
    this.m_SignDate = l.doubleValue();

    this.m_CheckSumVersion = 1;

    this.STSize = (HeaderBytes[82] & 0xFF | (HeaderBytes[83] & 0xFF) << 8 | (HeaderBytes[84] & 0xFF) << 16 | (HeaderBytes[85] & 0xFF) << 24);

    this.Trace_Info = HeaderBytes[86];
  }

  private void readContent(byte[] ContentArray)
  {
    int strcopy = 0;
    char[] mychar = new char[10];
    if (this.STSize > 0) {
      byte[] m_SignTrace = new byte[this.STSize + 1];
      strcopy = newvalue - 87 - this.STSize - 1 - 1;
      System.arraycopy(ContentArray, 0, m_SignTrace, 0, this.STSize + 1);
      int curPos = this.STSize + 1;
      if (ContentArray[curPos] != 0) {
        this.m_managerUID = readUID(ContentArray, curPos);
        curPos += 16;
        strcopy = newvalue - 87 - this.STSize - 1 - 17;
      }
      byte[] StringBytes = new byte[strcopy];

      String wholeString = dumpStringBytes(StringBytes, ContentArray, curPos + 1, 0, strcopy);

      this.index_extpoints = wholeString.indexOf("EXTPOINTS");
      this.extpoints_exist = false;
      if (this.index_extpoints >= 0) {
        this.extpoints_exist = true;
      }

      StringTokenizer st = new StringTokenizer(wholeString, "\b");
      this.m_signerName = st.nextToken();
      this.m_signerName = extractString(this.m_signerName);

      this.m_signerDesignation = st.nextToken();
      this.m_signerDesignation = this.m_signerDesignation.substring(1);
      this.m_signerDesignation = extractString(this.m_signerDesignation);

      this.m_signerOrganisation = st.nextToken();
      this.m_signerOrganisation = this.m_signerOrganisation.substring(1);
      this.m_signerOrganisation = extractString(this.m_signerOrganisation);

      this.m_signerAddress = st.nextToken();
      this.m_signerAddress = this.m_signerAddress.substring(1);
      this.m_signerAddress = extractString(this.m_signerAddress);

      this.m_signerRemarks = st.nextToken();
      this.m_signerRemarks = this.m_signerRemarks.substring(1);
      this.m_signerRemarks = extractString(this.m_signerRemarks);

      this.m_signPassword = st.nextToken();
      this.m_signPassword = this.m_signPassword.substring(1);
      this.m_signPassword = extractString(this.m_signPassword);

      this.m_version = st.nextToken();
      this.m_version = this.m_version.substring(1);
      this.m_version = extractString(this.m_version);

      StringTokenizer st1 = new StringTokenizer(this.m_version, "~");
      this.m_version = st1.nextToken();
      this.m_deviceinfo = st1.nextToken();

      if (this.extpoints_exist)
      {
        int start_index = curPos + this.index_extpoints + 9 + 1;
        int signtraceEx_len = ContentArray.length - start_index - 1;
        byte[] m_SignTraceEx = new byte[signtraceEx_len];
        System.arraycopy(ContentArray, start_index + 1, m_SignTraceEx, 0, signtraceEx_len);

        bytesToArrayEx(m_SignTraceEx);
      }
      else {
        bytesToArray(m_SignTrace);
      }
    }
  }

  private void bytesToArrayEx(byte[] signtrace_ex)
  {
    int TPASize = 0;
    int UDTSize = 0;
    int byteIndex = 0;

    int datalen = signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24;

    byteIndex += 4;
    byte[] tempbytes = new byte[signtrace_ex.length - datalen - 4];
    String CompleteString = dumpStringBytes(tempbytes, signtrace_ex, datalen + 4, 0, signtrace_ex.length - datalen - 4);

    this.index_devextpoints = CompleteString.indexOf("DEVEXTENTS");
    this.devextpoints_exist = false;
    if (this.index_devextpoints >= 0) {
      this.devextpoints_exist = true;
    }

    this.MaxX = (signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24);

    byteIndex += 4;
    this.MaxY = (signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24);

    byteIndex += 8;
    this.MinX = (signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24);

    byteIndex += 4;
    this.MinY = (signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24);

    byteIndex += 4;
    this.MinTime = (signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24);

    byteIndex += 4;
    this.MinPressure = (signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24);

    byteIndex += 4;
    this.MinSequenceNo = (signtrace_ex[byteIndex] & 0xFF | (signtrace_ex[(byteIndex + 1)] & 0xFF) << 8 | (signtrace_ex[(byteIndex + 2)] & 0xFF) << 16 | (signtrace_ex[(byteIndex + 3)] & 0xFF) << 24);

    byteIndex += 4;
    this.Trace_InfoEx = signtrace_ex[byteIndex];
    datalen -= 37;
    byte[] Sign_Trace = new byte[datalen];
    System.arraycopy(signtrace_ex, 37, Sign_Trace, 0, datalen);

    if ((this.Trace_InfoEx & 0x1) != 0)
      UDTSize += 1;
    else {
      UDTSize += 2;
    }
    if ((this.Trace_InfoEx & 0x2) != 0)
      UDTSize += 1;
    else {
      UDTSize += 2;
    }

    if ((this.Trace_InfoEx & 0x4) != 0)
      UDTSize += 2;
    else {
      UDTSize += 4;
    }

    if ((this.Trace_InfoEx & 0x8) != 0)
      UDTSize += 1;
    else {
      UDTSize += 4;
    }

    if ((this.Trace_InfoEx & 0x10) != 0)
      UDTSize += 1;
    else {
      UDTSize += 4;
    }

    TPASize = (Sign_Trace.length + 1) / UDTSize;
    this.m_NoOfPointsEx = ((short)TPASize);
    this.signPointsEx = new Vector(this.m_NoOfPoints);
    int k = 0;
    byteIndex = 0;
    for (k = 0; k <= this.m_NoOfPointsEx - 1; k++) {
      TracePoint tpEx = new TracePoint();
      if ((this.Trace_InfoEx & 0x1) != 0)
      {
        tpEx.x = (this.MinX + (Sign_Trace[byteIndex] & 0xFF));
        byteIndex += 1;
      }
      else {
        tpEx.x = (this.MinX + (Sign_Trace[byteIndex] & 0xFF | (Sign_Trace[(byteIndex + 1)] & 0xFF) << 8));

        byteIndex += 2;
      }

      if ((this.Trace_InfoEx & 0x2) != 0)
      {
        tpEx.y = (this.MinY + (Sign_Trace[byteIndex] & 0xFF));
        byteIndex += 1;
      }
      else {
        tpEx.y = (this.MinY + (Sign_Trace[byteIndex] & 0xFF | (Sign_Trace[(byteIndex + 1)] & 0xFF) << 8));

        byteIndex += 2;
      }

      if ((this.Trace_InfoEx & 0x4) != 0)
      {
        tpEx.timer = (this.MinTime + (Sign_Trace[byteIndex] & 0xFF | (Sign_Trace[(byteIndex + 1)] & 0xFF) - 127 << 8));

        tpEx.mouseStatus = ((Sign_Trace[(byteIndex + 1)] & 0xFF) < 128);
        byteIndex += 2;
      }
      else
      {
        tpEx.timer = (this.MinTime + (Sign_Trace[byteIndex] & 0xFF | (Sign_Trace[(byteIndex + 1)] & 0xFF) << 8 | (Sign_Trace[(byteIndex + 2)] & 0xFF) << 16 | (Sign_Trace[(byteIndex + 3)] & 0xFF) - 127 << 24));

        tpEx.mouseStatus = ((Sign_Trace[(byteIndex + 3)] & 0xFF) < 128);
        byteIndex += 4;
      }

      if ((this.Trace_InfoEx & 0x8) != 0)
      {
        tpEx.Pressure = (this.MinPressure + (Sign_Trace[byteIndex] & 0xFF));
        byteIndex++;
      }
      else {
        tpEx.Pressure = (this.MinPressure + (Sign_Trace[byteIndex] & 0xFF | (Sign_Trace[(byteIndex + 1)] & 0xFF) << 8 | (Sign_Trace[(byteIndex + 2)] & 0xFF) << 16 | (Sign_Trace[(byteIndex + 3)] & 0xFF) << 24));

        byteIndex += 4;
      }

      if ((this.Trace_InfoEx & 0x10) != 0)
      {
        tpEx.SequenceNo = (this.MinSequenceNo + (Sign_Trace[byteIndex] & 0xFF));
        byteIndex++;
      }
      else
      {
        tpEx.SequenceNo = (this.MinSequenceNo + (Sign_Trace[byteIndex] & 0xFF | (Sign_Trace[(byteIndex + 1)] & 0xFF) << 8 | (Sign_Trace[(byteIndex + 2)] & 0xFF) << 16 | (Sign_Trace[(byteIndex + 3)] & 0xFF) << 24));

        byteIndex += 4;
      }
      this.signPointsEx.addElement(tpEx);
    }
    if (this.devextpoints_exist)
    {
      readDeviceExtents(tempbytes);
    }

    this.m_isSigned = true;
  }

  private void readDeviceExtents(byte[] devextents)
  {
    int byteIndex = 11;
    int datalen = devextents[byteIndex] & 0xFF | (devextents[(byteIndex + 1)] & 0xFF) << 8 | (devextents[(byteIndex + 2)] & 0xFF) << 16 | (devextents[(byteIndex + 3)] & 0xFF) << 24;

    byteIndex += 4;

    byte[] dataBytes = new byte[datalen];
    System.arraycopy(devextents, byteIndex, dataBytes, 0, datalen);
    long tempLongx = 0L;
    long tempLongy = 0L;
    for (int i = 0; i < 8; i++) {
      tempLongx |= (dataBytes[i] & 0xFF) << i * 8;

      tempLongy |= (dataBytes[(i + 8)] & 0xFF) << i * 8;
    }
    
    Long lx = new Long(tempLongx);
    this.dev_physicalX = lx.doubleValue();
    
    Long ly = new Long(tempLongy);
    this.dev_physicalY = ly.doubleValue();

  }

  private String extractString(String s)
  {
    char[] mychar = new char[s.length() / 2];
    int l = 0; int m = 0; int n = 0;
    int i = 0; for (int p = 0; i <= s.length() - 1; p++) {
      l = s.charAt(i);
      i++;
      m = s.charAt(i);
      n = l + m * 256;
      mychar[p] = ((char)n);

      i++;
    }

    return new String(mychar);
  }

  private String readUID(byte[] thisArray, int Index)
  {
    this.uid = new byte[16];
    char[] mychar = new char[2];
    int uByte = 0; int firstHex = 0; int secondHex = 0;
    String wholeStr = "";
    String str = "";
    for (int i = 0; i <= 15; i++) {
      this.uid[i] = thisArray[Index];
      uByte = thisArray[Index];
      uByte = 128 + uByte;
      firstHex = uByte % 16;
      secondHex = uByte / 16;
      mychar[0] = Character.forDigit(firstHex, 16);
      mychar[1] = Character.forDigit(secondHex, 16);
      str = new String(mychar);
      wholeStr = wholeStr + str;
      Index++;
    }
    return wholeStr;
  }

  private String dumpStringBytes(byte[] dest, byte[] source, int SOffset, int dOffset, int CopyLength)
  {
    int i = 0;
    char[] myChar = new char[CopyLength];
    for (i = 0; i <= CopyLength - 1; i++) {
      dest[(i + dOffset)] = source[(i + SOffset)];
      myChar[i] = ((char)dest[(i + dOffset)]);
    }
    return new String(myChar);
  }

  private void bytesToArray(byte[] TraceBytes)
  {
    int TPASize = 0;
    int UDTSize = 1;
    if ((this.Trace_Info & 0x1) != 0)
      UDTSize += 1;
    else {
      UDTSize += 2;
    }
    if ((this.Trace_Info & 0x2) != 0)
      UDTSize += 2;
    else {
      UDTSize += 4;
    }
    TPASize = (this.STSize + 1) / UDTSize;
    this.m_NoOfPoints = ((short)TPASize);
    this.signPoints = new Vector(this.m_NoOfPoints);
    int k = 0; int byteIndex = 0;
    for (k = 0; k <= this.m_NoOfPoints - 1; k++) {
      TracePoint tp = new TracePoint();

      if ((this.Trace_Info & 0x1) != 0) {
        tp.x = (TraceBytes[byteIndex] & 0xFF);
        byteIndex++;
      }
      else {
        tp.x = (TraceBytes[byteIndex] & 0xFF | (TraceBytes[(byteIndex + 1)] & 0xFF) << 8);

        byteIndex += 2;
      }
      tp.y = (TraceBytes[byteIndex] & 0xFF);
      byteIndex++;
      if ((this.Trace_Info & 0x2) != 0) {
        tp.timer = (TraceBytes[byteIndex] & 0xFF | (TraceBytes[(byteIndex + 1)] & 0xFF) - 127 << 8);

        tp.mouseStatus = ((TraceBytes[(byteIndex + 1)] & 0xFF) < 128);

        byteIndex += 2;
      } else {
        tp.timer = (TraceBytes[byteIndex] & 0xFF | (TraceBytes[(byteIndex + 1)] & 0xFF) << 8 | (TraceBytes[(byteIndex + 2)] & 0xFF) << 16 | (TraceBytes[(byteIndex + 3)] & 0xFF) - 127 << 24);

        tp.mouseStatus = ((TraceBytes[(byteIndex + 3)] & 0xFF) < 128);
        byteIndex += 4;
      }

      this.signPoints.addElement(tp);
    }
    this.m_isSigned = true;
  }

  private synchronized void drawSign(Graphics g) {
    Rectangle rng = getBounds();
    if (this.signPoints.size() > 0)
    {
      float scaleValue = 1.0F;
      int wOffset = 0; int hOffset = 0;
      float wRatio = (this.m_signWidth + 4 * this.m_penWidth) / (rng.width - 3);

      float hRatio = (this.m_signHeight + 4 * this.m_penWidth) / (rng.height - 3);

      if (hRatio > wRatio) {
        scaleValue = 1.0F / hRatio;
        wOffset = (int)(rng.width - 3 - this.m_signWidth * scaleValue) / 2;

        hOffset = (int)(2 * this.m_penWidth * scaleValue) + 4;
      } else {
        scaleValue = 1.0F / wRatio;
        hOffset = (int)(rng.height - 3 - this.m_signHeight * scaleValue) / 2;

        wOffset = (int)(2 * this.m_penWidth * scaleValue) + 4;
      }
      this.lastFlag = true;
      TracePoint tempPoint = (TracePoint)this.signPoints.elementAt(0);
      for (int i = 1; i < this.signPoints.size(); i++) {
        tempPoint = (TracePoint)this.signPoints.elementAt(i);
        putPoint(tempPoint, g, scaleValue, wOffset, hOffset);
        this.prevPoint = tempPoint;
      }
    }
    this.lastFlag = true;
  }

  private synchronized void drawSignEx(Graphics g)
  {
    Rectangle rng = getBounds();
    if (this.signPointsEx.size() > 0)
    {
      this.lastFlag = true;
      TracePoint tempPoint = (TracePoint)this.signPointsEx.elementAt(0);

      for (int i = 0; i < this.signPointsEx.size(); i++) {
        tempPoint = (TracePoint)this.signPointsEx.elementAt(i);
        if (tempPoint.mouseStatus) {
          if (this.lastFlag)
          {
            g.setColor(this.m_signColor);
            int xone = tempPoint.x * rng.width / this.MaxX;
            int yone = tempPoint.y * rng.height / this.MaxY;
            int xtwo = tempPoint.x * rng.width / this.MaxX;
            int ytwo = tempPoint.y * rng.height / this.MaxY;
            drawLine(xone, yone, xtwo, ytwo, g);
            this.lastFlag = false;
          }
          else {
            g.setColor(this.m_signColor);
            int xone = this.prevPoint.x * rng.width / this.MaxX;
            int yone = this.prevPoint.y * rng.height / this.MaxY;
            int xtwo = tempPoint.x * rng.width / this.MaxX;
            int ytwo = tempPoint.y * rng.height / this.MaxY;

            drawLine(xone, yone, xtwo, ytwo, g);
          }

        }
        else
        {
          this.lastFlag = true;
        }
        this.prevPoint = tempPoint;
      }
    }
    this.lastFlag = true;
  }

  private void drawSignEx1(Graphics g)
  {
    Toolkit tk = Toolkit.getDefaultToolkit();
    int dpi = tk.getScreenResolution();

    Rectangle rng = getBounds();

    double xLengthPx = rng.getWidth();
    double yLengthPx = rng.getHeight();
    double xLengthInInches = xLengthPx / dpi;
    double yLengthInInches = yLengthPx / dpi;

    if (!this.m_EnableWhiteSpaceRemoval) {
      if (this.signPointsEx.size() > 0)
      {
        this.lastFlag = true;
        double WidthRatio = 0.0D; double HeightRatio = 0.0D; double PCMaxXY = 0.0D;
        WidthRatio = rng.width / this.dev_physicalX;
        HeightRatio = rng.height / this.dev_physicalY;
        if (HeightRatio > WidthRatio)
          PCMaxXY = WidthRatio;
        else {
          PCMaxXY = HeightRatio;
        }
        TracePoint tempPoint = (TracePoint)this.signPointsEx.elementAt(0);
        for (int i = 1; i < this.signPointsEx.size(); i++) {
          tempPoint = (TracePoint)this.signPointsEx.elementAt(i);
          if (tempPoint.mouseStatus) {
            if (this.lastFlag)
            {
              g.setColor(this.m_signColor);
              double xone = this.dev_physicalX * tempPoint.x / this.MaxX;
              xone *= PCMaxXY;
              double yone = this.dev_physicalY * tempPoint.y / this.MaxY;
              yone *= PCMaxXY;
              double xtwo = this.dev_physicalX * tempPoint.x / this.MaxX;
              xtwo *= PCMaxXY;
              double ytwo = this.dev_physicalY * tempPoint.y / this.MaxY;
              ytwo *= PCMaxXY;
              boolean rounding = true;

              int Px1 = 0; int Py1 = 0; int Px2 = 0; int Py2 = 0;
              if (rounding) {
                if (xone >= 0.0D)
                  Px1 = (int)(xone + 0.5D);
                else {
                  Px1 = (int)(xone - 0.5D);
                }

                if (yone >= 0.0D)
                  Py1 = (int)(yone + 0.5D);
                else {
                  Py1 = (int)(yone - 0.5D);
                }
                Px2 = Px1;
                Py2 = Py1;
              } else {
                Px1 = (int)xone;
                Px2 = (int)xone;
                Py1 = (int)yone;
                Py2 = (int)yone;
              }

              drawLine(Px1, Py1, Px2, Py2, g);
              this.lastFlag = false;
            }
            else {
              g.setColor(this.m_signColor);
              double xone = this.dev_physicalX * this.prevPoint.x / this.MaxX;
              xone *= PCMaxXY;
              double yone = this.dev_physicalY * this.prevPoint.y / this.MaxY;
              yone *= PCMaxXY;
              double xtwo = this.dev_physicalX * tempPoint.x / this.MaxX;
              xtwo *= PCMaxXY;
              double ytwo = this.dev_physicalY * tempPoint.y / this.MaxY;
              ytwo *= PCMaxXY;
              boolean rounding = true;
              int Px1 = 0; int Py1 = 0; int Px2 = 0; int Py2 = 0;
              if (rounding) {
                if (xone >= 0.0D)
                  Px1 = (int)(xone + 0.5D);
                else {
                  Px1 = (int)(xone - 0.5D);
                }

                if (yone >= 0.0D)
                  Py1 = (int)(yone + 0.5D);
                else {
                  Py1 = (int)(yone - 0.5D);
                }
                if (xtwo >= 0.0D)
                  Px2 = (int)(xtwo + 0.5D);
                else {
                  Px2 = (int)(xone - 0.5D);
                }

                if (ytwo >= 0.0D)
                  Py2 = (int)(ytwo + 0.5D);
                else
                  Py2 = (int)(ytwo - 0.5D);
              }
              else {
                Px1 = (int)xone;
                Px2 = (int)xtwo;
                Py1 = (int)yone;
                Py2 = (int)ytwo;
              }

              drawLine(Px1, Py1, Px2, Py2, g);
            }

          }
          else
          {
            this.lastFlag = true;
          }
          this.prevPoint = tempPoint;
        }
      }
      this.lastFlag = true;
    } else {
      if (this.signPointsEx.size() > 0) {
        this.lastFlag = true;

        int LocalMaxX = 0; int LocalMaxY = 0; int LocalMinX = 99999;
        int LocalMinY = 99999;
        for (int i = 1; i < this.signPointsEx.size(); i++)
        {
          TracePoint tempPoint = (TracePoint)this.signPointsEx.elementAt(i);

          if (tempPoint.x < LocalMinX) {
            LocalMinX = tempPoint.x;
          }

          if (tempPoint.y < LocalMinY)
          {
            LocalMinY = tempPoint.y;
          }

          if (tempPoint.x > LocalMaxX) {
            LocalMaxX = tempPoint.x;
          }

          if (tempPoint.y > LocalMaxY) {
            LocalMaxY = tempPoint.y;
          }

        }

        Vector tempPoints = new Vector(this.signPointsEx.size());
        for (int i = 1; i < this.signPointsEx.size(); i++) {
          TracePoint tempPoint = (TracePoint)this.signPointsEx.elementAt(i);
          int x = tempPoint.x - LocalMinX;
          int y = tempPoint.y - LocalMinY;
          Point crrPoint = new Point(x, y);
          TracePoint currTracePoint = new TracePoint(crrPoint, tempPoint.mouseStatus, tempPoint.timer, tempPoint.Pressure, tempPoint.SequenceNo);

          tempPoints.add(currTracePoint);
        }

        int sizeX = LocalMaxX - LocalMinX + 1;
        int sizeY = LocalMaxY - LocalMinY + 1;

        double DeviceX1 = 0.0D; double DeviceY1 = 0.0D;

        DeviceX1 = sizeX * this.dev_physicalX / this.MaxX;
        DeviceY1 = sizeY * this.dev_physicalY / this.MaxY;
        double xScale = 0.0D; double yScale = 0.0D; double scale = 0.0D;
        xScale = xLengthInInches / DeviceX1;
        yScale = yLengthInInches / DeviceY1;

        scale = xScale;
        if (xScale > yScale) {
          scale = yScale;
        }

        if ((scale > 1.0D) && 
          (this.m_EnableMaxEnlargementFactor)) {
          if (this.m_MaxEnlargementFactor > scale)
            scale = scale;
          else {
            scale = this.m_MaxEnlargementFactor;
          }
        }

        scale = 0.95D * scale;

        double xOffset = 0.0D; double yOffset = 0.0D;
        xOffset = (xLengthInInches - DeviceX1 * scale) / 2.0D * dpi;

        yOffset = (yLengthInInches - DeviceY1 * scale) / 2.0D * dpi;

        for (int i = 1; i < tempPoints.size(); i++) {
          TracePoint tempPoint = (TracePoint)tempPoints.elementAt(i);
          if (tempPoint.mouseStatus) {
            if (this.lastFlag)
            {
              g.setColor(this.m_signColor);

              double xone = tempPoint.x * DeviceX1 * scale / sizeX * dpi;

              double yone = tempPoint.y * DeviceY1 * scale / sizeY * dpi;

              double xtwo = tempPoint.x * DeviceX1 * scale / sizeX * dpi;

              double ytwo = tempPoint.y * DeviceY1 * scale / sizeY * dpi;

              xone += xOffset;
              yone += yOffset;
              xtwo += xOffset;
              ytwo += yOffset;

              boolean rounding = true;

              int Px1 = 0; int Py1 = 0; int Px2 = 0; int Py2 = 0;
              if (rounding) {
                if (xone >= 0.0D)
                  Px1 = (int)(xone + 0.5D);
                else {
                  Px1 = (int)(xone - 0.5D);
                }

                if (yone >= 0.0D)
                  Py1 = (int)(yone + 0.5D);
                else {
                  Py1 = (int)(yone - 0.5D);
                }
                Px2 = Px1;
                Py2 = Py1;
              } else {
                Px1 = (int)xone;
                Px2 = (int)xone;
                Py1 = (int)yone;
                Py2 = (int)yone;
              }

              drawLine(Px1, Py1, Px2, Py2, g);
              this.lastFlag = false;
            }
            else {
              g.setColor(this.m_signColor);
              double xone = this.prevPoint.x * DeviceX1 * scale / sizeX * dpi;

              double yone = this.prevPoint.y * DeviceY1 * scale / sizeY * dpi;

              double xtwo = tempPoint.x * DeviceX1 * scale / sizeX * dpi;

              double ytwo = tempPoint.y * DeviceY1 * scale / sizeY * dpi;

              xone += xOffset;
              yone += yOffset;
              xtwo += xOffset;
              ytwo += yOffset;
              boolean rounding = true;
              int Px1 = 0; int Py1 = 0; int Px2 = 0; int Py2 = 0;
              if (rounding) {
                if (xone >= 0.0D)
                  Px1 = (int)(xone + 0.5D);
                else {
                  Px1 = (int)(xone - 0.5D);
                }

                if (yone >= 0.0D)
                  Py1 = (int)(yone + 0.5D);
                else {
                  Py1 = (int)(yone - 0.5D);
                }
                if (xtwo >= 0.0D)
                  Px2 = (int)(xtwo + 0.5D);
                else {
                  Px2 = (int)(xone - 0.5D);
                }

                if (ytwo >= 0.0D)
                  Py2 = (int)(ytwo + 0.5D);
                else
                  Py2 = (int)(ytwo - 0.5D);
              }
              else {
                Px1 = (int)xone;
                Px2 = (int)xtwo;
                Py1 = (int)yone;
                Py2 = (int)ytwo;
              }

              drawLine(Px1, Py1, Px2, Py2, g);
            }

          }
          else
          {
            this.lastFlag = true;
          }
          this.prevPoint = tempPoint;
        }
      }

      this.lastFlag = true;
    }
  }

  private void putPoint(TracePoint thisPoint, Graphics g, float scale, int wOffset, int hOffset)
  {
    if (thisPoint.mouseStatus) {
      if (this.lastFlag)
      {
        g.setColor(this.m_signColor);
        int xone = (int)(thisPoint.x * scale) + wOffset;
        int yone = (int)(thisPoint.y * scale) + hOffset;
        int xtwo = (int)(thisPoint.x * scale) + wOffset;
        int ytwo = (int)(thisPoint.y * scale) + hOffset;
        drawLine(xone, yone, xtwo, ytwo, g);
        this.lastFlag = false;
      }
      else {
        g.setColor(this.m_signColor);
        int xone = (int)(this.prevPoint.x * scale) + wOffset;
        int yone = (int)(this.prevPoint.y * scale) + hOffset;
        int xtwo = (int)(thisPoint.x * scale) + wOffset;
        int ytwo = (int)(thisPoint.y * scale) + hOffset;

        drawLine(xone, yone, xtwo, ytwo, g);
      }

    }
    else
    {
      this.lastFlag = true;
    }
  }

  private void drawLine(int x1, int y1, int x2, int y2, Graphics g)
  {
    Graphics2D g2d = (Graphics2D)g;
    Stroke stroke = new BasicStroke(this.m_penWidthX, 1, 1);

    g2d.setStroke(stroke);

    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    Line2D line = new Line2D.Double(x1, y1, x2, y2);

    g2d.draw(line);
  }

  public byte[] getBytes()
  {
    if (isSigned())
    {
      if (this.m_SignerUID.length() == 36) {
        for (int i = 0; i < 36; i += 2) {
          this.rawBytes[(i + 10)] = ((byte)(Character.digit(this.m_SignerUID.charAt(i), 16) & 0xF | Character.digit(this.m_SignerUID.charAt(i + 1), 16) & 0xF0));
        }

      }

      System.arraycopy(this.m_checksum, 0, this.rawBytes, 49, 16);
      this.rawBytes[81] = this.m_CheckSumVersion;
      ByteArrayOutputStream bosenc = new ByteArrayOutputStream();
      ByteArrayInputStream bisenc = null;

      if ((this.rawBytes != null) && (this.rawBytes.length > 0))
      {
        if (this.devextpoints_exist) {
          int byteslength = this.rawBytes.length;
          byte[] rawBytesTemp = new byte[byteslength + 8];
          System.arraycopy(this.rawBytes, 0, rawBytesTemp, 0, byteslength);
          for (int i = 0; i < 8; i++) {
            rawBytesTemp[(byteslength + i)] = 0;
          }
          bisenc = new ByteArrayInputStream(rawBytesTemp);
        } else {
          bisenc = new ByteArrayInputStream(this.rawBytes);
        }
        byte[] key = { 65, 0, 100, 0, 101, 0, 112, 0, 116, 0, 101, 0, 107, 0, 83, 0, 111, 0, 102, 0, 116, 0 };

        encrypt(bisenc, bosenc, key);
        this.S = new int[4][256];
        return bosenc.toByteArray();
      }
      return null;
    }
    return null;
  }

  public int verifyDocument(IDocInfo idi)
  {
    if (!this.m_isSigned) {
      return 4;
    }
    this.rehash = true;
    String msg = "Some internal problem";
    byte hversion = idi.getVersion();
    idi.feedGrabber(this);
    int res = verifyDocument1(hversion);
    if (res == 1)
      this.m_tampered = true;
    else {
      this.m_tampered = false;
    }

    repaint();
    return res;
  }

  private int verifyDocument1(byte hversion)
  {
    boolean compresult = true;
    boolean isallzeros = true;
    byte csv = this.m_CheckSumVersion;
    if (csv == hversion) {
      for (int i = 0; i <= 15; i++)
      {
        if (this.cs[i] != this.m_checksum[i]) {
          compresult = false;
        }
        if (this.m_checksum[i] != 0) {
          isallzeros = false;
        }
      }
      if (isallzeros)
        return 3;
      if (compresult) {
        return 0;
      }
      return 1;
    }

    return 2;
  }

  public String getString()
  {
    if ((this.rawBytes != null) && (this.rawBytes.length > 0)) {
      return new Base64Format().encode64(getBytes());
    }
    return null;
  }

  public void grabBytes(byte[] impData)
  {
    if (this.md5 != null)
      this.md5.update(impData);
  }

  public String getDocID()
  {
    return "Not Implemented";
  }

  public void finishGrab() {
    if (this.md5 != null)
      if (!this.rehash) {
        this.m_checksum = this.md5.digest();
        this.md5.reset();
      } else {
        this.cs = this.md5.digest();
        this.md5.reset();
      }
  }

  public Container getContainer()
  {
    return getParent();
  }

  private void initializeBlowFish(byte[] key)
  {
    this.P = new int[18];
    this.P[0] = 608135816;
    this.P[1] = -2052912941;
    this.P[2] = 320440878;
    this.P[3] = 57701188;
    this.P[4] = -1542899678;
    this.P[5] = 698298832;
    this.P[6] = 137296536;
    this.P[7] = -330404727;
    this.P[8] = 1160258022;
    this.P[9] = 953160567;
    this.P[10] = -1101764913;
    this.P[11] = 887688300;
    this.P[12] = -1062458953;
    this.P[13] = -914599715;
    this.P[14] = 1065670069;
    this.P[15] = -1253635817;
    this.P[16] = -1843997223;
    this.P[17] = -1988494565;
    short i = 0; short j = 0; short k = 0;
    int data = 0;
    System.arraycopy(ks0, 0, this.S[0], 0, 256);
    System.arraycopy(ks1, 0, this.S[1], 0, 256);
    System.arraycopy(ks2, 0, this.S[2], 0, 256);
    System.arraycopy(ks3, 0, this.S[3], 0, 256);
    j = 0;
    for (i = 0; i < 18; i = (short)(i + 1)) {
      data = 0;
      for (k = 0; k < 4; k = (short)(k + 1)) {
        data = data << 8 | key[j];
        j = (short)(j + 1);
        if (j >= key.length) {
          j = 0;
        }
      }
      this.P[i] ^= data;
    }
    this.xleft = 0;
    this.xright = 0;
    for (i = 0; i < 18; i = (short)(i + 2)) {
      encipher(this.xleft, this.xright);
      this.P[i] = this.xleft;
      this.P[(i + 1)] = this.xright;
    }
    for (i = 0; i < 4; i = (short)(i + 1))
      for (j = 0; j < 256; j = (short)(j + 2)) {
        encipher(this.xleft, this.xright);
        this.S[i][j] = this.xleft;
        this.S[i][(j + 1)] = this.xright;
      }
  }

  private void encrypt(InputStream dataIn, OutputStream dataOut, byte[] key)
  {
       //TODO
  }

  private void decrypt(OutputStream dataOut, InputStream dataIn, byte[] key)
  {
       //TODO
  }

  private void encipher(int xl, int xr)
  {
    for (short i = 0; i < 16; i = (short)(i + 1)) {
      xl ^= this.P[i];
      xr = F(xl) ^ xr;
      int temp = xl;
      xl = xr;
      xr = temp;
    }
    int temp = xl;
    xl = xr;
    xr = temp;

    this.xright = (xr ^ this.P[16]);
    this.xleft = (xl ^ this.P[17]);
  }

  private void decipher(int xl, int xr) {
    int temp = 0;
    short i = 0;

    for (i = 17; i > 1; i = (short)(i - 1)) {
      xl ^= this.P[i];
      xr = F(xl) ^ xr;

      temp = xl;
      xl = xr;
      xr = temp;
    }

    temp = xl;
    xl = xr;
    xr = temp;

    this.xright = (xr ^ this.P[1]);
    this.xleft = (xl ^ this.P[0]);
  }

  private int F(int x) {
    short a = 0; short b = 0; short c = 0; short d = 0;
    int y = 0;
    d = (short)(x & 0xFF);
    x >>= 8;
    c = (short)(x & 0xFF);
    x >>= 8;
    b = (short)(x & 0xFF);
    x >>= 8;
    a = (short)(x & 0xFF);

    y = this.S[0][a] + this.S[1][b];
    y ^= this.S[2][c];
    y += this.S[3][d];
    return y;
  }

  private void write(int val, OutputStream os) throws IOException
  {
    boolean isNegative = val < 0;
    if (isNegative) {
      val = 2147483647 - Math.abs(val) + 1;
    }
    byte b1 = 0;
    for (int i = 0; i < 4; i++) {
      b1 = (byte)(val % 256);
      val /= 256;
      if (i < 3) {
        os.write(b1);
      }
    }
    if (isNegative)
      os.write((byte)(128 + b1));
    else
      os.write(b1);
  }
}